/*
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package utopiaintelpackage.survey;

import java.text.NumberFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import main.CommonMethods;

import org.jibble.pircbot.Colors;

import tools.UtopiaTime;
import utopiaintelpackage.AbstractIntel;

/**
 * This class represents a Survey The class offers convenience methods for adding and removing commonly used parameters
 * 
 * 
 */
public class Survey extends AbstractIntel {
   private int totalbuilt = 0;
   private int totalunbuilt = 0;
   private boolean selfSurvey = false;

   public int getBuilding(final String buildingtype) {
	  if (getParameter(buildingtype) == null)
		 return 0;
	  return (Integer) getParameter(buildingtype);
   }

   public int getBuildingInProgress(final String buildingtype) {
	  if (getParameter(buildingtype + " in progress") == null)
		 return 0;
	  return (Integer) getParameter(buildingtype + " in progress");
   }

   public String getExportLine() {
	  if (getParameter("export") == null)
		 return "";
	  return (String) getParameter("export");
   }

   @Override
   public List<String> getIRCOutput(final boolean shortVersion) {
	  List<String> out = new LinkedList<String>();
	  String adderPers = CommonMethods.getPersonality(getSavedBy());
	  out.add(">> " + Colors.OLIVE + getName() + getKdloc() + Colors.NORMAL + " << " + Colors.OLIVE + getRace() + " "
			+ getPersonality() + Colors.NORMAL
			+ (adderPers.equals("Tactician") ? Colors.BOLD + " Tactician-" + Colors.NORMAL : " ") + "Survey added: "
			+ UtopiaTime.compareTimes(getUpdated().getTime()) + " ago"
			+ ("".equals(getSavedBy()) ? "" : " by " + Colors.NORMAL + "o" + Colors.RED + getSavedBy() + Colors.NORMAL + "o"));

	  if (shortVersion) {
		 out.add("Export:" + Colors.DARK_GREEN + " " + getExportLine());
	  } else {
		 LinkedList<String> part1 = new LinkedList<String>(); // building
		 // name
		 LinkedList<String> part2 = new LinkedList<String>(); // amount
		 LinkedList<String> part3 = new LinkedList<String>(); // percent
		 int land = 0;
		 List<String> buildingList = CommonMethods.listBuildings();
		 for (final String building : buildingList) { // calculate
			// total built land
			if (getBuilding(building) > 0 || getBuildingInProgress(building) > 0) {
			   land += getBuilding(building) + getBuildingInProgress(building);
			}
		 }
		 land = Math.max(land, 1);
		 NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
		 nf.setGroupingUsed(false);
		 nf.setMaximumFractionDigits(1);
		 nf.setMinimumFractionDigits(1);

		 for (final String building : buildingList) { // assemble the
			// 3
			// different
			// sub
			// strings
			if (getBuilding(building) > 0 || getBuildingInProgress(building) > 0) {
			   part1.add(Colors.BLUE + building + ":");
			   part2.add(Colors.OLIVE + getBuilding(building)
					 + (getBuildingInProgress(building) > 0 ? " +" + getBuildingInProgress(building) : ""));
			   part3.add(Colors.NORMAL
					 + "("
					 + nf.format(100.0 * getBuilding(building) / land)
					 + "%"
					 + (getBuildingInProgress(building) > 0 ? " +" + nf.format(100.0 * getBuildingInProgress(building) / land)
						   + "%" : "") + ")");
			}
		 }

		 int maxName = 0;
		 int maxAmount = 0;
		 int maxPercent = 0;
		 for (int i = 0; i < part1.size(); ++i) { // calculate the
			// max length of
			// each sub
			// string
			if (part1.get(i).length() > maxName) {
			   maxName = part1.get(i).length() + 1;
			}
			if (part2.get(i).length() > maxAmount) {
			   maxAmount = part2.get(i).length() + 1;
			}
			if (part3.get(i).length() > maxPercent) {
			   maxPercent = part3.get(i).length() + 1;
			}
		 }

		 for (int i = 0; i < part1.size(); ++i) { // format all sub
			// strings - make them the same length
			String name = String.format("%1$-" + maxName + "s", part1.get(i));
			String amount = String.format("%1$-" + maxAmount + "s", part2.get(i));
			String percent = String.format("%1$-" + maxPercent + "s", part3.get(i));
			part1.set(i, name + amount + percent);
		 }

		 Collections.sort(part1);
		 for (final String s : part1) {
			out.add(s);
		 }
		 if (!"".equals(getExportLine())) {
			out.add("Export:" + Colors.DARK_GREEN + " " + getExportLine());
		 }
	  }
	  return out;
   }

   public String getKdloc() {
	  if (getParameter("kdloc") == null)
		 return "";
	  return (String) getParameter("kdloc");
   }

   public Integer getLand() {
	  if (getParameter("land") == null)
		 return 0;
	  return (Integer) getParameter("land");
   }

   public String getName() {
	  if (getParameter("name") == null)
		 return "";
	  return (String) getParameter("name");
   }

   public String getPersonality() {
	  if (getParameter("personality") == null)
		 return "";
	  return (String) getParameter("personality");
   }

   public String getRace() {
	  if (getParameter("race") == null)
		 return "";
	  return (String) getParameter("race");
   }

   @Override
   public Map<String, Object> getRPCOutput(final int... args) {
	  Map<String, Object> out = new HashMap<String, Object>();
	  Map<String, Integer> built = new HashMap<String, Integer>();
	  Map<String, Integer> inProgress = new HashMap<String, Integer>();
	  for (final String building : CommonMethods.listBuildings()) {
		 if (getBuilding(building) != 0) {
			built.put(building, getBuilding(building));
		 }
		 if (getBuildingInProgress(building) != 0) {
			inProgress.put(building, getBuildingInProgress(building));
		 }
	  }
	  out.put("Name", getName());
	  out.put("KD", getKdloc());
	  out.put("Land", getLand());
	  out.put("Race", getRace());
	  out.put("Personality", getPersonality());
	  out.put("Buildings", built);
	  out.put("In Progress", inProgress);
	  out.put("Export Line", getExportLine());
	  out.put("Saved By", getSavedBy());
	  out.put("Added Time", getUpdated());
	  return out;
   }

   public String getSavedBy() {
	  if (getParameter("savedby") == null)
		 return "";
	  return (String) getParameter("savedby");
   }

   public int getTotalbuilt() {
	  return totalbuilt;
   }

   public int getTotalprogress() {
	  return isSelfSurvey() ? totalunbuilt : getLand() == 0 ? 0 : getLand() - totalbuilt - getBuilding("Barren Land");
   }

   @Override
   public String getTypeOfIntel() {
	  return "Survey";
   }

   public Date getUpdated() {
	  return (Date) getParameter("updated");
   }

   @Override
   public boolean isComplete() {
	  return getParameter("name") != null && getParameter("updated") != null && getParameter("kdloc") != null
			&& getIntel().size() > 3;
   }

   public boolean isSelfSurvey() {
	  return selfSurvey;
   }

   public void setBuilding(final String buildingtype, final int amount) {
	  setParameter(buildingtype, amount);
	  if (!"Barren Land".equals(buildingtype)) {
		 totalbuilt += amount;
	  }
   }

   public void setBuildingInProgress(final String buildingtype, final int amount) {
	  setParameter(buildingtype + " in progress", amount);
	  totalunbuilt += amount;
   }

   public void setExportLine(final String exportLine) {
	  setParameter("export", exportLine);
   }

   public void setKdloc(final String kdloc) {
	  setParameter("kdloc", kdloc);
   }

   public void setLand(final int land) {
	  setParameter("land", land);
   }

   public void setName(final String name) {
	  setParameter("name", name);
   }

   public void setPersonality(final String personality) {
	  setParameter("personality", personality);
   }

   public void setRace(final String race) {
	  setParameter("race", race);
   }

   public void setSavedBy(final String savedBy) {
	  setParameter("savedby", savedBy);
   }

   public void setSelfSurvey(final boolean selfSurvey) {
	  this.selfSurvey = selfSurvey;
   }

   public void setUpdated(final Date updated) {
	  setParameter("updated", updated);
   }
}
